<?php

namespace Duomai\Translation\Gateways;

use Duomai\Translation\Contracts\Translation;
use Duomai\Translation\Exceptions\GatewayException;
use Duomai\Translation\Exceptions\InvalidArgumentException;
use Duomai\Translation\Traits\HasHttpRequest;
use Duomai\Translation\Utils\Config;

/**
 * 创建时间:2024/3/20 15:38
 * Class AliyunGateway
 * @package Duomai\Translation\Gateways
 * @see 官方文档：https://help.aliyun.com/zh/machine-translation/developer-reference/using-rest-api?spm=a2c4g.11186623.0.i8
 */
class AliyunGateway implements Translation
{
    use HasHttpRequest;

    /**
     * aliyun api.
     * @var string
     */
    protected $gateway = 'https://mt.cn-hangzhou.aliyuncs.com/api/translate/web/ecommerce';

    /**
     * user_config.
     * @var Config
     */
    protected $config;

    /**
     * construct.
     * @param array $config
     *
     */
    public function __construct(array $config)
    {
        $this->config = new Config($config);

        if(is_null($this->config->get('appid')) || is_null($this->config->get('appsecret'))){
            throw new InvalidArgumentException("missing config [appid] or [appsecret]", 1);
        }
    }

    /**
     * translate.
     *
     * @param string $q
     * @param string $to
     * @param string $from
     *
     * @return string
     */
    public function trans($q, $to = 'en', $from = 'auto')
    {
        $datas = [
            'SourceLanguage' => $from, // 源语言，auto表示自动检测
            'TargetLanguage' => $to, // 目标语言
            'SourceText' => $q, // 要翻译的文本
            'FormatType' => 'text',
            'Scene' => 'general',

            "RegionId" => "cn-hangzhou",
            "Format" => "JSON",
            "SignatureMethod" => "HMAC-SHA1",
            "SignatureVersion" => "1.0",
            "Action" => "TranslateGeneral",
            "Version" => "2018-10-12",
            "SignatureNonce" => md5($q . uniqid(md5(microtime(true)), true)) . microtime(),
            "Timestamp" => gmdate('Y-m-d\TH:i:s\Z'),
            "AccessKeyId" => $this->config->get('appid'),
        ];

        try{
            //生成签名
            $datas['Signature'] = $this->signature($datas);
            $result = $this->post($this->gateway, $datas);

            if($result['Code'] != '200'){
                throw new GatewayException('get result error, error code' . $result['Code'], $result['Message'], $result);
            }
            return trim($result['Data']['Translated'], "\n");
        }catch(\Throwable $e){
            throw new GatewayException('get result error:' . $e->getMessage(), $e->getCode());
        }
    }

    /**
     * Sign the parameters.
     *
     * @return mixed
     * @throws ClientException
     * @throws ServerException
     */
    public function signature($params)
    {
        ksort($params);
        $canonicalized = '';
        foreach($params as $key => $value){
            if($value === null || $value === ''){
                continue;
            }
            $canonicalized .= '&' . $this->percentEncode($key) . '=' . $this->percentEncode($value);
        }

        $stringToSign = 'POST&%2F&' . $this->percentEncode(substr($canonicalized, 1));
        return base64_encode(hash_hmac('sha1', $stringToSign, $this->config->get('appsecret') . '&', true));
    }

    /**
     * @param string $string
     * @return null|string|string[]
     */
    private function percentEncode($string)
    {
        $result = urlencode($string);
        $result = str_replace(['+', '*'], ['%20', '%2A'], $result);
        $result = preg_replace('/%7E/', '~', $result);

        return $result;
    }

    public function uuid()
    {
        return sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
            mt_rand(0, 0xffff), mt_rand(0, 0xffff),
            mt_rand(0, 0xffff),
            mt_rand(0, 0x0fff) | 0x4000,
            mt_rand(0, 0x3fff) | 0x8000,
            mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff)
        );
    }

}
